﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BusClustering.Utility
{
    public static class Utils
    {
        public static double R = 6371;

        public static double CalculateDistance(double latitude1, double longitude1, double latitude2, double longitude2)
        {
            
            double deltaX = Math.Cos(latitude2) * Math.Cos(longitude2) - Math.Cos(latitude1) * Math.Cos(longitude1);
            double deltaY = Math.Cos(latitude2) * Math.Sin(longitude2) - Math.Cos(latitude1) * Math.Sin(longitude1);
            double deltaZ = Math.Sin(latitude2) - Math.Sin(latitude1);

            double c = Math.Sqrt(Math.Pow(deltaX, 2) + Math.Pow(deltaY, 2) + Math.Pow(deltaZ, 2));
            double deltaSigma = 2 * Math.Asin(c / 2);

            return R * deltaSigma * 1000;
        }

        public static List<MyPoint> Cluster(List<BusTracking> lst, double epsilon, int minpts)
        {
            List<MyPoint> lstPoint = new List<MyPoint>();
            List<Cluster> clusters = new List<Cluster>();
            foreach (BusTracking tracking in lst)
            {
                double minD = Double.MaxValue;
                int minI = 0;
                if (clusters.Count == 0)
                {
                    Cluster c = new Cluster(1, tracking.Latitude, tracking.Longitude);
                    clusters.Add(c);

                    MyPoint tPoint = new MyPoint();
                    tPoint.ClusterId = 0;
                    tPoint.Tracking = tracking;
                    lstPoint.Add(tPoint);


                }
                else
                {
                    for (int i = 0; i < clusters.Count; i++)
                    {
                        double calculateDistance = CalculateDistance(tracking.Latitude, tracking.Longitude, clusters[i].Latitude, clusters[i].Longitude);
                        if (calculateDistance < minD)
                        {
                            minD = calculateDistance;
                            minI = i;
                        }

                        if (minD <= epsilon)
                        {
                            MyPoint tPoint = new MyPoint();
                            tPoint.ClusterId = i;
                            tPoint.Tracking = tracking;

                            lstPoint.Add(tPoint);

                            clusters[i].Latitude = ((clusters[i].Size * clusters[i].Latitude) + tracking.Latitude) / (clusters[i].Size + 1);
                            clusters[i].Longitude = ((clusters[i].Size * clusters[i].Longitude) + tracking.Longitude) / (clusters[i].Size + 1);
                            clusters[i].Size++;

                        }
                        else
                        {
                            Cluster c = new Cluster(clusters.Count, tracking.Latitude, tracking.Longitude);
                            clusters.Add(c);

                            MyPoint tPoint = new MyPoint();
                            tPoint.ClusterId = clusters.Count;
                            tPoint.Tracking = tracking;
                            lstPoint.Add(tPoint);
                        }
                    }
                }

            }
            return lstPoint;
        }
    }
}
